/**
 * Copyright 2014 ABSir's Studio
 * 
 * All right reserved
 *
 * Create on 2014-4-24 上午10:39:54
 */
package com.absir.appserv.system.service;

import java.io.IOException;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;

import com.absir.appserv.configure.JConfigureUtils;
import com.absir.appserv.system.bean.JPayTrade;
import com.absir.appserv.system.bean.value.JePayStatus;
import com.absir.appserv.system.configure.JWeiXinConfigure;
import com.absir.appserv.system.helper.HelperClient;
import com.absir.appserv.system.helper.HelperEncrypt;
import com.absir.appserv.system.helper.HelperJson;
import com.absir.appserv.system.helper.HelperRandom;
import com.absir.bean.inject.value.Bean;
import com.absir.core.kernel.KernelCharset;
import com.absir.core.kernel.KernelDyna;
import com.absir.core.kernel.KernelObject;
import com.absir.core.kernel.KernelString;

/**
 * @author absir
 * 
 */
@Bean
public class WeiXinService implements IPayInterface, IPayOrder {

	/** WEIXIN_CONFIGURE */
	public static final JWeiXinConfigure WEIXIN_CONFIGURE = JConfigureUtils.getConfigure(JWeiXinConfigure.class);

	/** PLAT_FORM_NAME */
	public static final String PLAT_FORM_NAME = "WeiXin";

	/** ORDER_QUERY_URL */
	protected static final String ORDER_QUERY_URL = "https://api.mch.weixin.qq.com/pay/orderquery";

	/** ORDER_UNIFIED_URL */
	protected static final String ORDER_UNIFIED_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";

	/**
	 * @param transaction_id
	 * @param out_trade_no
	 * @return
	 * @throws IOException
	 */
	public Map<String, Object> queryOrder(String transaction_id, String out_trade_no) throws IOException {
		if (KernelString.isEmpty(WEIXIN_CONFIGURE.getAppid()) || KernelString.isEmpty(WEIXIN_CONFIGURE.getPartnerId())) {
			return null;
		}

		return queryOrder(WEIXIN_CONFIGURE.getAppid(), WEIXIN_CONFIGURE.getPartnerId(), WEIXIN_CONFIGURE.getMerchantKey(),
				transaction_id, out_trade_no);
	}

	/**
	 * @param appid
	 *            公众账号ID
	 * @param mch_id
	 *            商户号
	 * @param merchantKey
	 *            商户私钥
	 * @param transaction_id
	 *            微信订单号
	 * @param out_trade_no
	 *            商户订单号
	 * @return
	 * @throws IOException
	 */
	public Map<String, Object> queryOrder(String appid, String mch_id, String merchantKey, String transaction_id,
			String out_trade_no) throws IOException {
		String nonce_str = HelperRandom.randSecendId();
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("appid", appid);
		map.put("mch_id", mch_id);
		if (out_trade_no == null) {
			map.put("transaction_id", transaction_id);

		} else {
			map.put("out_trade_no", out_trade_no);
		}

		map.put("nonce_str", nonce_str);
		String sign = HelperJson.builderSignSort(map, "&key=" + merchantKey, null).toString();
		map.put("sign", HelperEncrypt.encryptionMD5(sign).toUpperCase());
		return HelperJson.xmlToMap(HelperClient.openConnection(ORDER_QUERY_URL, true, HelperJson.mapToXmlBuilder(map, null)
				.getBytes(KernelCharset.UTF8), String.class));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.absir.appserv.system.service.IPayInterface#validator(com.absir.appserv
	 * .system.bean.JPayTrade)
	 */
	@Override
	public boolean validator(JPayTrade payTrade) throws Exception {
		// 获取请求对象
		Map<String, Object> orderDetail = queryOrder(payTrade.getTradeNo(), payTrade.getId());
		if (orderDetail != null && !KernelObject.equals("USERPAYING", orderDetail.get("trade_state"))) {
			if (KernelObject.equals("SUCCESS", orderDetail.get("trade_state"))
					&& KernelDyna.to(orderDetail.get("total_fee"), float.class) / 100 >= payTrade.getAmount()) {
				if (payTrade.getStatus() != JePayStatus.PAYED) {
					payTrade.setStatus(JePayStatus.PAYED);
					BeanService.ME.merge(payTrade);
				}

				return true;

			} else {
				if (payTrade.getStatus() != JePayStatus.ERROR) {
					payTrade.setStatus(JePayStatus.ERROR);
					BeanService.ME.merge(payTrade);
				}
			}
		}

		return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.absir.appserv.system.service.IPayOrder#order(com.absir.appserv.system
	 * .bean.JPayTrade, java.util.Map)
	 */
	@Override
	public Object order(JPayTrade payTrade, Map<String, Object> paramMap) throws Exception {
		// TODO Auto-generated method stub
		if (KernelString.isEmpty(WEIXIN_CONFIGURE.getAppid())) {
			return null;
		}

		paramMap.put("appid", WEIXIN_CONFIGURE.getAppid());
		paramMap.put("mch_id", WEIXIN_CONFIGURE.getPartnerId());
		paramMap.put("out_trade_no", payTrade.getId());
		paramMap.put("total_fee", (int) (payTrade.getAmount() * 100));
		paramMap.put("notify_url", WEIXIN_CONFIGURE.getNotifyUrl());
		Map<String, Object> orderDetail = orderCommon(payTrade, paramMap, WEIXIN_CONFIGURE.getMerchantKey());
		if (orderDetail != null && KernelObject.equals("SUCCESS", orderDetail.get("result_code"))) {
			payTrade.setTradeNo(KernelDyna.to(orderDetail.get("prepay_id"), String.class));
			BeanService.ME.merge(payTrade);
		}

		orderDetail.put("tradeId", payTrade.getId());
		orderDetail.put("dollar", payTrade.getAmount());
		return orderDetail;
	}

	/**
	 * @param payTrade
	 * @param paramMap
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public Map<String, Object> orderCommon(JPayTrade payTrade, Map<String, Object> paramMap, String signKey) throws Exception {
		if (!paramMap.containsKey("nonce_str")) {
			paramMap.put("nonce_str", HelperRandom.randSecendId());
		}

		if (!paramMap.containsKey("spbill_create_ip")) {
			paramMap.put("spbill_create_ip", InetAddress.getLocalHost().getHostAddress().toString());
		}

		paramMap.put("sign", HelperEncrypt.encryptionMD5(HelperJson.builderSignSort(paramMap, "&key=" + signKey, null).toString()));
		String xmlString = HelperJson.mapToXmlBuilder(paramMap, null);
		return HelperJson.xmlToMap(HelperClient.openConnection(ORDER_UNIFIED_URL, true, xmlString.getBytes(KernelCharset.UTF8),
				String.class));
	}
}
